package com.ellecity06.common.delegate

import android.os.Parcelable
import com.tencent.mmkv.MMKV
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

/**
 * @author ellecity06
 * @time 2023/3/29 15:26
 * @des 利用kotlin的委托属性对mmkv封装
 */
private const val MMKV_MMAP_ID = "CWHISKY_PDA"
private const val MMKV_CRYPT_KEY = "CWHISKY_PDA_KEY"

/**
 * mmkv实例
 */
val mmkv: MMKV by lazy { MMKV.mmkvWithID(MMKV_MMAP_ID, MMKV.MULTI_PROCESS_MODE, MMKV_CRYPT_KEY) }

/**
 * 存储一个int,
 * @param
 */
fun mmkvInt(key: String? = null, default: Int = 0) =
    MMKVNoNullProperty({ mmkv.decodeInt(it, default) }, { mmkv.encode(first, second) }, key)

/**
 * 存储一个Long
 */
fun mmkvLong(key: String? = null, default: Long = 0L) =
    MMKVNoNullProperty({ mmkv.decodeLong(it, default) }, { mmkv.encode(first, second) }, key)

/**
 * 存储一个Bool
 */
fun mmkvBool(key: String? = null, default: Boolean = false) =
    MMKVNoNullProperty({ mmkv.decodeBool(it, default) }, { mmkv.encode(first, second) }, key)

/**
 * 存储一个Float
 */
fun mmkvFloat(key: String? = null, default: Float = 0f) =
    MMKVNoNullProperty({ mmkv.decodeFloat(it, default) }, { mmkv.encode(first, second) }, key)

/**
 * 存储一个Double
 */
fun mmkvDouble(key: String? = null, default: Double = 0.0) =
    MMKVNoNullProperty({ mmkv.decodeDouble(it, default) }, { mmkv.encode(first, second) }, key)

/**
 * 存储一个String
 */
fun mmkvString(key: String? = null, default: String? = null) =
    MMKVProperty({ mmkv.decodeString(it) ?: default }, { mmkv.encode(first, second) }, key)

/**
 * 存储一个StringSet
 */
fun mmkvStringSet(key: String? = null, default: Set<String>? = null) =
    MMKVProperty({ mmkv.decodeStringSet(it) ?: default }, { mmkv.encode(first, second) }, key)

/**
 * 存储一个Bytes(
 */
fun mmkvBytes(key: String? = null, default: ByteArray? = null) =
    MMKVProperty({ mmkv.decodeBytes(it) ?: default }, { mmkv.encode(first, second) }, key)

/**
 * 存储一个Parcelable
 */
inline fun < reified T : Parcelable> mmkvParcelable(key: String? = null, default: T? = null) =
    MMKVProperty({ mmkv.decodeParcelable(it, T::class.java) ?: default }, { mmkv.encode(first, second) }, key)

/**
 * mmkv 委托类,允许指定一个key来存储数据，当没有指定key时，会取这个委托人的name来作为key存储数据
 */
class MMKVProperty<V>(
    private val decode: (String) -> V?,
    private val encode: Pair<String, V>.() -> Boolean,
    private val key: String? = null
) :
    ReadWriteProperty<Any?, V?> {
    private var cache: V? = null

    override fun getValue(thisRef: Any?, property: KProperty<*>): V? = cache ?: decode(key ?: property.name).also { cache = it }

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: V?) {
        if (value != null) {
            if (encode((key ?: property.name) to value)) {
                cache = value
            }
        }

    }
}
class MMKVNoNullProperty<V>(
    private val decode: (String) -> V,
    private val encode: Pair<String, V>.() -> Boolean,
    private val key: String? = null
) :
    ReadWriteProperty<Any?, V> {
    private var cache: V? = null

    override fun getValue(thisRef: Any?, property: KProperty<*>): V = cache ?: decode(key ?: property.name).also { cache = it }

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: V) {
        if (value != null) {
            if (encode((key ?: property.name) to value)) {
                cache = value
            }
        }

    }
}